package com.oauth2.web;

import com.alibaba.fastjson.JSON;
import com.oauth2.constant.Constants;
import com.oauth2.domain.JsonResult;
import com.oauth2.domain.UserEntity;
import com.oauth2.service.IUserService;
import com.oauth2.util.CookieUtil;
import com.oauth2.util.HttpClientUtil;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @author shipeilei
 * @date 2020-7-16 10:56:34
 * @desc desc
 */
@Controller
public class LoginController {
    private final IUserService iUserService;

    public LoginController(IUserService iUserService) {
        this.iUserService = iUserService;
    }

    @RequestMapping("/login")
    public String index() {
        return "login";
    }

    @RequestMapping("/handleLogin")
    @ResponseBody
    public JsonResult handleLogin(HttpServletResponse response, UserEntity userEntity) {
        String username, password;
        if (null != userEntity && !StringUtils.isEmpty(username = userEntity.getUsername()) && !StringUtils.isEmpty(password = userEntity.getPassword())) {
            Map<String, Object> resMap;
            try {
                resMap = validateCode(username, password);
            }catch (Exception e) {
                return JsonResult.fail(e.getMessage());
            }
            Object token = resMap.get("access_token");
            if (null != token) {
                //Token保存到Cookie
                CookieUtil.addCookie(response, Constants.COOKIE_TOKEN_KEY, token + "", 3000);
            }
            String accessToken = OAuth2AccessToken.BEARER_TYPE + " " + token;
            resMap.put("access_token", accessToken);
            return new JsonResult(JsonResult.SUCCESS, "success", resMap);
        } else {
            return JsonResult.fail("账号、密码不能为空");
        }
    }

    @GetMapping("/refreshToken")
    @ResponseBody
    public JsonResult refreshToken(HttpServletRequest request, HttpServletResponse response) {
        try {
            String refreshToken = request.getParameter("refreshToken");
            Assert.notNull(refreshToken,"refreshToken不存在");
            final Map<String, String> parameters = new HashMap<String, String>();
            parameters.put("grant_type", Constants.GRANT_TYPE_REFRESH_TOKEN);
            parameters.put("client_id", Constants.CLIENT_ID);
            parameters.put("client_secret", Constants.CLIENT_SECRET);
            parameters.put("refresh_token", refreshToken);
            String result = HttpClientUtil.doPost(Constants.OAUTH_TOKEN_URL, parameters, null);
            Map tokenInfo = JSON.parseObject(result, Map.class);
            String token = (String) tokenInfo.get("access_token");
            if (null != token) {
                //Token保存到Cookie
                CookieUtil.addCookie(response, Constants.COOKIE_TOKEN_KEY, token + "", 3000);
            }
            String accessToken = OAuth2AccessToken.BEARER_TYPE + " " + token;
            tokenInfo.put("access_token", accessToken);
            return new JsonResult(JsonResult.SUCCESS, "success", tokenInfo);
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    private Map<String, Object> validateCode(String userName, String userPwd) {
        final Map<String, Object> resMap = new HashMap<String, Object>();
        UserEntity entity = iUserService.findByUsername(userName);
        Assert.notNull(entity,"用户名不存在");
        String password = entity.getPassword();
        Assert.isTrue(new BCryptPasswordEncoder().matches(userPwd, password),"客户端密钥不正确");
        final Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("grant_type", Constants.GRANT_TYPE_PASSWORD);
        parameters.put("client_id", Constants.CLIENT_ID);
        parameters.put("client_secret", Constants.CLIENT_SECRET);
        parameters.put("username", userName);
        parameters.put("password", userPwd);
        String result = HttpClientUtil.doPost(Constants.OAUTH_TOKEN_URL, parameters, null);
        return JSON.parseObject(result, Map.class);
    }
}
